#include "cacheAlloc.h"
#include <thread>

 
void BenchmarkMalloc(size_t ntimes, size_t nworks, size_t rounds)
{
    std::vector<std::thread> vthread(nworks);
    size_t malloc_costtime = 0;
    size_t free_costtime = 0;
 
    for (size_t k = 0; k < nworks; ++k)
    {
        vthread[k] = std::thread([&, k]() {
            std::vector<void*> v;
            v.reserve(ntimes);
 
            for (size_t j = 0; j < rounds; ++j)
            {
                size_t begin1 = clock();
                for (size_t i = 0; i < ntimes; i++)
                {
                    v.push_back(malloc(16));
                }
                size_t end1 = clock();
 
                size_t begin2 = clock();
                for (size_t i = 0; i < ntimes; i++)
                {
                    free(v[i]);
                }
                size_t end2 = clock();
                v.clear();
 
                malloc_costtime += end1 - begin1;
                free_costtime += end2 - begin2;
            }
        });
    }
 
    for (auto& t : vthread)
    {
        t.join();
    }
 
	printf("%u个线程并发执行 %u 轮次，每轮次alloc %u次：花费: %u ms\n", nworks, rounds, ntimes, malloc_costtime);
	printf("%u个线程并发执行 %u 轮次，每轮次dealloc %u次：花费: %u ms\n", nworks, rounds, ntimes, free_costtime);
	printf("%u个线程并发alloc&dealloc %u次：总计花费: %u ms\n", nworks, nworks * rounds * ntimes, malloc_costtime + free_costtime);

}
 
 
// 单轮次申请释放次数 线程数 轮次
void BenchmarkConcurrentMalloc(size_t ntimes, size_t nworks, size_t rounds)
{
    std::vector<std::thread> vthread(nworks);
    size_t malloc_costtime = 0;
    size_t free_costtime = 0;
 
    for (size_t k = 0; k < nworks; ++k)
    {
        vthread[k] = std::thread([&]() {
            std::vector<int*> v;
            v.reserve(ntimes);
 
            for (size_t j = 0; j < rounds; ++j)
            {
                size_t begin1 = clock();
                for (size_t i = 0; i < ntimes; i++)
                {
                    //void* ptr = cAlloc(16);
                    //std::cout << "alloc: " << ptr << std::endl;

                    v.push_back((int*)cAlloc(sizeof(int)));
                }
                size_t end1 = clock();
 
                size_t begin2 = clock();
                for (size_t i = 0; i < ntimes; i++)
                {
                    *v[i] = 1;
                    std::cout << "free: " << v[i] << ":" << *v[i] << std::endl;
                    cFree(v[i]);
                }
                size_t end2 = clock();
                v.clear();
 
                malloc_costtime += end1 - begin1;
                free_costtime += end2 - begin2;
            }
        });
    }
 
    for (auto& t : vthread)
    {
        t.join();
    }
 
	printf("%u个线程并发执 %u 轮次，每轮次alloc %u次：花费: %u ms\n", nworks, rounds, ntimes, malloc_costtime);
	printf("%u个线程并发执行 %u 轮次，每轮次dealloc %u次：花费: %u ms\n", nworks, rounds, ntimes, free_costtime);
	printf("%u个线程并发alloc&dealloc %u次：总计花费: %u ms\n", nworks, nworks * rounds *ntimes, malloc_costtime + free_costtime);
}
 
int main()
{
    SetConsoleOutputCP(65001);
    std::cout << "==========================================================" << std::endl;
    BenchmarkMalloc(10000, 5, 100);
    std::cout << std::endl << std::endl;
 
    BenchmarkConcurrentMalloc(10000, 5, 100);
    std::cout << "==========================================================" << std::endl;
 
    //system("pause");
    return 0;
}

//g++ testcache.cpp cacheThread.cpp cacheCentral.cpp cachePage.cpp cacheObjectPool.cpp logger.cpp -o cachemain -std=c++11 -llog4cxx -g

// int main()
// {
//     int* p = reinterpret_cast<int*>(cAlloc(sizeof(int)));
//     *p = 1;
//     std::cout << p << ":" << *p << std::endl;

//     int *p1 = reinterpret_cast<int*>(cAlloc(sizeof(int)));
//     std::cout << p1 << ":" << *p1 << std::endl;
//     int *p2 = reinterpret_cast<int*>(cAlloc(sizeof(int)));
//     std::cout << p2 << ":" << *p2 << std::endl;
//     int *p3 = reinterpret_cast<int*>(cAlloc(sizeof(int)));
//     std::cout << p3 << ":" << *p3 << std::endl;

//     qSpan* sp = reinterpret_cast<qSpan*>(cAlloc(sizeof(qSpan)));
//     std::cout << sp << std::endl;

    
//     qSpan* sp1 = reinterpret_cast<qSpan*>(cAlloc(sizeof(qSpan)));
//     std::cout << sp1 << std::endl;

    
//     qSpan* sp2 = reinterpret_cast<qSpan*>(cAlloc(sizeof(qSpan)));
//     std::cout << sp2 << std::endl;

    
//     // qSpan* sp3 = reinterpret_cast<qSpan*>(cAlloc(sizeof(qSpan)));
//     // std::cout << sp3 << std::endl;

//     cFree(p);
//     cFree(p1);
//     cFree(p2);


//     return 0;
// }